#include "smart-device-manager.h"

void printVectorAsHex(const std::vector<uint8_t> &vec)
{
    for (size_t i = 0; i < vec.size(); ++i)
    {
        printf("%02X ", vec[i]); // %02X 格式化为两位16进制数，不足两位前面补0
    }
    printf("\n");
}

SmartDeviceManager::SmartDeviceManager(const string &uartDevice)
    : linuxUart(uartDevice)
{
}

bool SmartDeviceManager::sendPacket(const vector<uint8_t> &packet)
{
    return linuxUart.writeData(packet.data(), packet.size()) < 0 ? false : true;
}

bool SmartDeviceManager::recvPacket(vector<uint8_t> &packet)
{

    vector<uint8_t> packet1(SMART_DEVICE_PROTOCOL_PACKET_FIX_LEN);
    int ret = linuxUart.readFixLenData(packet1.data(), packet1.size());
    if (ret < 0)
    {
        fprintf(stderr, "Fail to readFixLenData\n");
        return false;
    }

    SmartDeviceProtocol protocol = SmartDeviceProtocol::makeProtocolFormPacket(packet1);
    vector<uint8_t> packet2(protocol.getPacketDataLen() + 2);

    ret = linuxUart.readFixLenData(packet2.data(), packet2.size());
    if (ret < 0)
    {
        fprintf(stderr, "Fail to readFixLenData\n");
        return false;
    }

    packet.insert(packet.end(), packet1.begin(), packet1.end());
    packet.insert(packet.end(), packet2.begin(), packet2.end());

    return true;
}

bool SmartDeviceManager::communication(SmartDeviceProtocol &protocol, vector<uint8_t> &ackData)
{

    vector<uint8_t> sendData = vector<uint8_t>(protocol.packetData(),
                                               protocol.packetData() + protocol.packetLen());

    cout << "--------打印send数据-----------" << endl;
    printVectorAsHex(sendData);

    // 发送： 请求
    bool ok = sendPacket(sendData);
    if (!ok)
    {
        fprintf(stderr, "Fail to openDoorlock sendPacket\n");
        return false;
    }
    // 接收：应答
    vector<uint8_t> ackPacket;
    ok = recvPacket(ackPacket);
    if (!ok)
    {
        fprintf(stderr, "Fail to openDoorlock recvPacket \n");
        return false;
    }

    SmartDeviceProtocol ackProtocol = SmartDeviceProtocol::makeProtocolFormPacket(ackPacket);
    if (ackProtocol.isErrorPakcet())
    {
        fprintf(stderr, "Ack packet is error \n");
        return false;
    }
    for (int i = 0; i < ackProtocol.getPacketDataLen(); i++)
    {
        ackData.push_back(ackProtocol.getPacketData()[i]);
    }

    return true;
}

bool SmartDeviceManager::openDoorlLock(uint8_t deviceType, uint8_t deviceNumber)
{
    SmartDeviceProtocol protocol = SmartDeviceProtocol::
        makeDoorLockProtocol(deviceType, SmartDeviceOpen, deviceNumber);

    vector<uint8_t> ackdata;
    bool ok = this->communication(protocol, ackdata);

    cout << "--------打印ackdata数据-----------" << endl;
    printVectorAsHex(ackdata);

    if (!ok)
    {
        fprintf(stderr, "Fail to openDoorlLock  \n");
        return false;
    }

    return ackdata[0] == SmartDeviceProtocol::HANDLE_SUCCESS;
}

bool SmartDeviceManager::closeDoorlLock(uint8_t deviceType, uint8_t deviceNumber)
{
    SmartDeviceProtocol protocol = SmartDeviceProtocol::
        makeDoorLockProtocol(deviceType, SmartDeviceClose, deviceNumber);

    vector<uint8_t> ackdata;
    bool ok = communication(protocol, ackdata);
    if (!ok)
    {
        fprintf(stderr, "Fail to communication  \n");
        return false;
    }

    return ackdata[0] == SmartDeviceProtocol::HANDLE_SUCCESS;
}

bool SmartDeviceManager::queryDoorlLock(uint8_t deviceType, uint8_t deviceNumber, uint8_t &lock_state)
{
    SmartDeviceProtocol protocol = SmartDeviceProtocol::
        makeDoorLockProtocol(deviceType, SmartDeviceQuery, deviceNumber);

    vector<uint8_t> ackdata;
    bool ok = communication(protocol, ackdata);
    if (!ok)
    {
        fprintf(stderr, "Fail to communication  \n");
        return false;
    }

    if (ackdata[0] != SmartDeviceProtocol::HANDLE_SUCCESS)
    {
        return false;
    }
    lock_state = ackdata[1];
    return true;
}

bool SmartDeviceManager::openElectrical(uint8_t deviceType, uint8_t deviceNumber)
{
    SmartDeviceProtocol protocol = SmartDeviceProtocol::
        makeElectricalProtocol(deviceType, SmartDeviceOpen, deviceNumber);

    vector<uint8_t> ackdata;
    bool ok = this->communication(protocol, ackdata);

    if (!ok)
    {
        fprintf(stderr, "Fail to openDoorlLock  \n");
        return false;
    }

    return ackdata[0] == SmartDeviceProtocol::HANDLE_SUCCESS;
}

bool SmartDeviceManager::closeElectrical(uint8_t deviceType, uint8_t deviceNumber)
{
    SmartDeviceProtocol protocol = SmartDeviceProtocol::makeElectricalProtocol(deviceType, SmartDeviceClose, deviceNumber);

    vector<uint8_t> ackData;
    bool ok = this->communication(protocol, ackData);
    if (!ok)
    {
        fprintf(stderr, "Fai to communication");
        return false;
    }
    return ackData[0] == SmartDeviceProtocol::HANDLE_SUCCESS;
}

bool SmartDeviceManager::queryElectrical(uint8_t deviceType, uint8_t deviceNumber, uint8_t &lockStatus)
{
    SmartDeviceProtocol protocol = SmartDeviceProtocol::makeElectricalProtocol(deviceType, SmartDeviceQuery, deviceNumber);

    vector<uint8_t> ackData;
    bool ok = this->communication(protocol, ackData);
    if (!ok)
    {
        fprintf(stderr, "Fai to communication");
        return false;
    }
    if (ackData[0] != SmartDeviceProtocol::HANDLE_SUCCESS)
    {
        return false;
    }

    lockStatus = ackData[1];
    return true;
}

bool SmartDeviceManager::querySensor(uint8_t deviceType, uint8_t deviceNumber, uint16_t &data)
{
    SmartDeviceProtocol protocol = SmartDeviceProtocol::makeSensorProtocol(deviceType, SmartDeviceQuery, deviceNumber);

    vector<uint8_t> ackData;
    bool ok = this->communication(protocol, ackData);
    if (!ok)
    {
        fprintf(stderr, "Fai to communication");
        return false;
    }
    if (ackData[0] != SmartDeviceProtocol::HANDLE_SUCCESS)
    {
        return false;
    }

    data = (ackData[1] << 8 | ackData[2]);
    return true;
}

bool SmartDeviceManager::sniffingDevice(uint8_t deviceType, uint8_t deviceNumber, vector<uint8_t> &info)
{
    SmartDeviceProtocol protocol = SmartDeviceProtocol::makeSniffingProtocol(deviceType, SmartDeviceQuery, deviceNumber);

    vector<uint8_t> ackData;
    bool ok = this->communication(protocol, ackData);
    if (!ok)
    {
        fprintf(stderr, "Fai to communication");
        return false;
    }
    if (ackData[0] != SmartDeviceProtocol::HANDLE_SUCCESS)
    {
        return false;
    }
    // 0 是错误码
    for (int i = 1; i < ackData.size(); i++)
    {
        info.push_back(ackData[i]);
    }
    return true;
}
